//
//  第二章 基础.swift
//  Documentation
//
//  Created by Toj on 10/13/23.
//

第二章 基础
开始于 第20页

/** git 的几个名词
 * 未追踪文件: 添加新文件
 * 已追踪文件:
 * 1. 添加新文件add 后变更已踪新文件;
 * 2. 本地仓库已存在的文件都是已追踪的文件
 * 工作区: 就是本地代码
 * 暂存区: 就是你修改的文件 git add 后添加到的区域
 * 本地仓库: git commit -m 后提交到的本地仓库
 * 远程仓库: 服务器仓库 git push <remote_name>
 */

// MARK: - 1. 仓库
1.1 初始化仓库
从当前目录初始化
git init
会出现一个.git 的目录

1.2. 克隆仓库
git clone 地址 new文件夹名
如果没有文件夹名 clone到当前文件夹内

// MARK: - 2. 文件记录状态更新到仓库
已跟踪文件: 指本来就被纳入版本控制管理的文件, 在上次快照中有它们的记录,
工作一段时间后, 它们的状态可能是未更新, 已修改或者 已放入暂存区

未跟踪文件: 其他所有文件都属于未跟踪文件.
它们既没有上次更新时的快照, 也不在当前的暂存区域.
初次克隆某个仓库时, 工作目录中的所有文件都属于已跟踪文件, 且状态为未修改

2.1 当前文件状态
git status

2.2 跟踪新文件 & 暂存状态
git add 文件名/ 路径/ .
文件名: 当前文件夹下某个文件
文件路径: 路径下具体文件路径
.: 全部文件

2.3 暂存已修改文件
git add 文件后再修改文件内容,
git status 查看文件状态 会出现1个文件2中状态
一个是暂存区的状态: 之前调用 git add 后的文件状态
一个是已修改的状态: git add 后修改了文件内容的状态
如果现在git commit 提交的是暂存区的文件内容,
想要提交当前内容需要再次git add 将内容添加到暂存区内

2.4 忽略某些不需要提交的文件
.gitignore 的文件
可以去github有专门统计的库
https://github.com/github/gitignore

.gitignore文件 的格式规范如下:
• 所有空行或者以注释符号 # 开头的行都会被 Git 忽略。
• 可以使用标准的 glob 模式匹配。
• 匹配模式最后跟􏰝斜杠(/)说明要忽略的是目录。
• 要忽略指定模式以外的文件或目录，可以在模式前加上惊叹号(!)取􏰝。


# 此为注释 – 将被 Git 忽略
*.a
# 忽略所有 .a 结尾的文件

!lib.a
# 但 lib.a 除外

/TODO
# 仅仅忽略项目根目录下的 TODO 文件，不包括 subdir/TODO build/ # 忽略 build/ 目录下的所有文件

doc/*.txt
# 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
*/

2.5 查看已暂存和未暂存的更新
git status 比较简单的看是否加入到暂存区
git diff   查看具体修改内容
此命令比较的是工作目录中当前文件 和 暂存区域快照之间的差异

git diff --cached
git diff --staged
此命令比较的是 已经暂存起来的文件 和 上次提交时的快照之间的差异

2.6 提交更新
git commit 会调用配置的编辑器 进行commit 操作
一般都是 vim 或 emacs
或者调用 git config --global core.editor 进行修改

可以在commit 后面加-m 参数省略编辑器提交过程
git commit -m "log"

在哪个分支提交; 生成的SHA-1校验; 提交了多少修订; 提交了什么文件;
[master（根提交） 5286bf7]  提交内容
 2 files changed, 14 insertions(+)
 create mode 100755 Mac config.txt
 create mode 100644 "\347\273\217\345\205\270\350\257\255\345\275\225"

2.7 跳过使用暂存区域
跳过git add 过程 直接提交
git commit -a -m 'log'
与其说跳过不如说2个命令合成1个命令

2.8 移除文件
2.8.1 移除某个文件
rm 文件名

2.8.2 已经加入到暂存区的文件
需要加入 -f参数, NOTE: f(force: 强制)
git rm -f 文件名
rm 文件名  一样效果

2.8.3 已经加入到暂存区, 但是不想删除文件, 只在暂存区删除文件
git rm --cached 文件名

2.8 移动文件
git mv file_from file_to

// MARK: - 3. 查看提交历史
git log
后面可以带参数
• -p: 显示提交的差异
git log -p
• --stat: 仅显示简要的增改行数统计
git log --stat
• --shortstat: 只显示 --stat 中最后的行数修改添加移除统计。
• --name-only: 仅在提交信息后显示已修改的文件清单。
• --name-status: 显示新增、修改、删除的文件清单。
• --abbrev-commit: 仅显示 SHA-1 的前几个字符，而非所有的 40 个字符。
• --relative-date: 使用较短的相对时间显示(比如，“2 weeks ago”)。
• --graph: 显示 ASCII 图形表示的分支合并历史。
• --pretty: 可以指定使用完全不同于默认格式的方式展示提交历史
git log --pretty=oneline
•• oneline: 将每个提交放在一行显示, 这在提交数很大时非常有用
•• short:
•• full:
•• fuller:
•• format: 可以定制要显示的记录格式
git log --pretty=format:"%h - %an, %ar : %s"
••• %H:  提交对象(commit)的完整哈希字串 %h 提交对象的简短哈希字串
••• %T:  树对象(tree)的完整哈希字串
••• %t:  树对象的简短哈希字串
••• %P:  父对象(parent)的完整哈希字串 %p 父对象的简短哈希字串
••• %an: 作者(author)的名字
••• %ae: 作者的电子邮件地址
••• %ad: 作者修订日期(可以用 -date= 选项定制格式) %ar 作者修订日期，按多久以前的方式显示
••• %cn: 提交者(committer)的名字
••• %ce: 提交者的电子邮件地址
••• %cd: 提交日期
••• %cr: 提交日期，按多久以前的方式显示 %s 提交说明

3.1 限制输出长度
git log --since=2.weeks

// MARK: - 4 撤消操作
4.1 修改最后一次提交的log
git commit --amend

如果在提交日志后, 还需要改动其他文件 & 这个提交也想包含这些修改内容
可以先加入到暂存区
git add .
然后再次
git commit --amend
输入 :wq退出即可,
如果想改log可以按i 进行编辑,
编辑完成后EXC
:wq退出

4.2 取消已经暂存的文件(下面都是执行某个文件)
首先创建二个文件分别叫做
first.swift
last.swift

有2个命令都可以做到效果
*** git restore
git add . 都添加到暂存区
git status 查看状态
```
要提交的变更：
  （使用 "git restore --staged <文件>..." 以取消暂存）
    新文件：   first.swift
    新文件：   last.swift
```
根据提示 git 让我们执行 `git restore --staged <文件>` 以取消暂存
撤销指定文件: git restore --staged [fileA|(fileA fileB)|.]

git status 再次查看状态
```
要提交的变更：
  （使用 "git restore --staged <文件>..." 以取消暂存）
    新文件：   last.swift
未跟踪的文件:
  （使用 "git add <文件>..." 以包含要提交的内容）
    first.swift
```
*** git reset
git add . 都添加到暂存区
撤销指定文件: git reset HEAD [fileA|(fileA fileB)|.]

NOTE: 当使用 git status会发现提示的是git restore --staged 命令
官方/ 版本不同reset 可能不推荐

4.3 取消对文件的修改
修改某些版本后如果想恢复到之前commit的版本
也是有2个命令可以实现
1. git checkout .
   git checkout -- .
效果一样 --可以省略
2. git restore .
文件/ 多文件/ 全部文件同上

不过git status 给出的提示是 git restore .
官方/ 版本不同checkout 可能不推荐

**
* 所有git提交过的都可以恢复, 前提是必须commit 过后,
* 如果没有commit 数据恢复了就丢失了无法恢复, 无从下手恢复
**

// MARK: - 5. 远程仓库
远程仓库 就是服务器仓库, 所有操作叫做本地仓库,
本地修改后需要同步到服务器仓库上

5.1 查看当前的远程库
git remote
输出结果:
```
origin
```
origin就是默认的远程仓库名


也可以加上 -v 选项(译注:此为—verbose 的简写，取首字母), 显示对应的克隆地址
git remote -v
输出结果:
```
origin    git@gitee.com:520it/git-pro.git (push)
```
多个仓库就是:
```
bakkdoor git://github.com/bakkdoor/grit.git
cho45 git://github.com/cho45/grit.git
defunkt git://github.com/defunkt/grit.git
koke git://github.com/koke/grit.git
origin git@gitee.com:520it/git-pro.git
```

5.2 添加远程仓库
git remote add [shortname] [url]
git remote add toj git@gitee.com:520it/git-toj.git (push)

5.3 从远程仓库抓取数据
有2张方式可以抓取数据
1. fetch
git fetch [remote-name]
*** 默认是origin仓库, 可以省略
但是发现执行完git fetch 后本地文件没有更改, 新文件没有拉取下来
*** git fetch 只是拉取文件引用,
*** 它是把 远程提交 拉取到 本地仓库, 而不是 本地工作目录.
需要再执行
git merge
把变更合并到本地工作目录

2. pull
git pull
它直接获取远程的最新提交，直接拉取并合并到本地工作目录

5.4 推送数据到远程仓库
提交(git commit)一些新数据后, 我们需要同步到服务器的远程仓库上, 就需要用到 push
git push [remote-name] [branch]
*** 默认
remote-name: 为origin仓库
branch: 是当前分支

如果是一个新分支
比如: testnewbranch
git push 会有提示
```
fatal: 当前分支 testnewbranch 没有对应的上游分支。
为推送当前分支并建立与远程上游的跟踪，使用
git push --set-upstream origin testnewbranch
```

5.5 查看远程仓库信息
git remote show [remote-name]
git remote show origin
```
* 远程 origin
* 远程 origin
  获取地址：git@gitee.com:520it/git-pro.git
  推送地址：git@gitee.com:520it/git-pro.git
  HEAD 分支：develop
  远程分支：
    develop  已跟踪
    gitFiles 已跟踪
    master   已跟踪
  为 'git pull' 配置的本地分支：
    develop  与远程 develop 合并
    gitFiles 与远程 gitFiles 合并
    master   与远程 master 合并
  为 'git push' 配置的本地引用：
    develop  推送至 develop  (最新)
    gitFiles 推送至 gitFiles (本地已过时)
    master   推送至 master   (最新)
```
能看到某个分支当前同步情况

5.6 远程仓库的删除和重命名
重命名:
git remote rename <old_name> <new_name>
e.g.:
git remote rename test to_test
git remote
```
origin
to_test
toj
```

删除:
git remote rm <remote-name>
git remote
```
origin
toj
```
// MARK: - 6. 打标签tag
发布每个版本后都会对这个版本做封板处理, 封板概念就是这个版本的终结
可以在这个时候做分支留档, 但是随着时间你的分支会很多, 显然不是一个最佳方案,
我们可以使用 git tag, 为每个版本做留档

6.1 列显已有的标签
6.1.1 全部标签
git tag
```
v0.0.1
v0.0.2
```
6.1.2 标签 筛选过滤
git tag 筛选过滤
git tag -l 'v0.0.*'

6.2 新建标签
两种标签类型, 一般使用含附注的类型
1. 轻量级的(lightweight)
2. 含附注的(annotated)

6.3 含附注的标签
创建一个含附注类型的标签 用 -a 指定标签名字即可
译注: a 取 annotated(标注的) 的首字母
译注: m 取 message(消息) 的首字母
git tag -a v0.0.3 -m '添加第三个版本tag'
git tag
```
v0.0.1
v0.0.2
v0.0.3
```
使用git show <tag_name> 查看tag信息

6.4 签署标签, 过因为没有签署私钥
如果你有自己的私钥, 还可以用 GPG 来签署标签, 只需要把之前的 -a 改为 -s
译注: s 取 Signed(签署) 的首字母
git tag -s v0.0.4 -m '添加v0.0.4日志'
```
error: cannot run gpg: No such file or directory
error: gpg 数据签名失败
error: 无法签署标签
```

6.5 轻量级标签
git tag v0.0.4
git show v0.0.4
显示就是一些commit提交log, 没有具体tag日志信息

6.6 为某个分支/ 提交HASH添加标签
6.6.1 分支 打tag
git tag -a <tag_name> -m 'log' <branch_name>
git tag -a v0.0.2.1 -m 'v0.0.2-1补丁tag标签日志' develop

6.6.2 commit 打tag
git tag -a <tag_name> -m 'log' <commit_hash>
git tag -a v0.0.2.2 -m 'v0.0.2-2补丁tag标签日志' a2e73eda1a9395d8dcf9298843898caae094fe1

6.7 tag提交到服务器
git push 默认不会把tag提交到服务器
需要在后面增加可选项
git push origin <tag_name>
git push origin v0.0.3

推送所有标签
git push origin --tags

6.8 命令别名
*** 不推荐, 会让你忘本
举个例子
git config --global alias.last 'log -1 HEAD'
git last
